import Router from "koa-router";
import multer from "@koa/multer";
import path from "path";
import fse from "fs-extra";
import { Result } from "@/utils/result";
import { Request } from "koa";

// {
//     fieldname: 'file',
//     originalname: '@-阿莘-03.jpg',
//     encoding: '7bit',
//     mimetype: 'image/jpeg',
//     destination: 'G:\\Demo\\koa-template\\upload\\temp',
//     filename: '@-阿莘-03.jpg_1697826074052.jpg',
//     path: 'G:\\Demo\\koa-template\\upload\\temp\\@-阿莘-03.jpg_1697826074052.jpg',
//     size: 214812
// }
interface file {
    fieldname: string;
    originalname: string;
    encoding: string;
    mimetype: string;
    destination: string;
    filename: string;
    path: string;
    size: number;
}

// 解决 ctx.request 上没有 files 对象的类型问题
type MyRequest = Request & {
    files?: file[];
};

const uploadRouter = new Router({ prefix: "/api/upload" });

const UPLOAD_DIR = "./upload/";
// 新建一个以 hash 为名的临时文件夹保存分片，然后读取分片合并成原始文件，然后删除临时文件夹
// 发现 req 中获取不到 hash 值，于是暂时固定一个临时文件夹使用，用完了就删，然后再新建。
// 但是这样就无法保存传了一半的文件了。
const tempDir = path.resolve(process.cwd(), "./upload/temp");

// 上传文件存储配置
const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        // console.log(req.body.hash); // req 中无法获取到 hash 值，用来创建临时文件夹
        // 确保临时文件夹存在，没有就创建它
        fse.ensureDirSync(tempDir);
        cb(null, tempDir);
    },
    filename: (req, file, cb) => {
        cb(null, `${file.originalname}_${Date.now()}${path.extname(file.originalname)}`);
    }
});

const upload = multer({ storage });

uploadRouter.get("/test", ctx => {
    return Result.ok(ctx, null, "get success");
});

// 解析 formdata 文件，分片上传
// array(字段)必须和前端发送的表单字段一致
uploadRouter.post("/", upload.array("file"), (ctx, dispatch) => {
    // const { filename, hash } = ctx.request.body;
    const req = ctx.request as MyRequest;
    if (!req.files) return Result.err(ctx, { code: -1001, msg: "no files" });
    const uploadFile: string[] = [];
    req.files.forEach(item => {
        uploadFile.push(item.originalname);
    });
    Result.ok(ctx, uploadFile, "post success");
});

// 合并分片
uploadRouter.post("/merge", async ctx => {
    const { filename, hash } = ctx.request.body as { filename: string; hash: string };

    // 获取文件后缀
    const ext = filename.slice(filename.lastIndexOf(".") + 1);

    // 从临时文件夹中获取分片
    const chunks = await fse.readdir(tempDir);

    // 将分片排序后，循环读入内存然后添加到一个文件中
    chunks
        .sort((a, b) => Number(a) - Number(b))
        .forEach(chunk => {
            // 合并文件
            fse.appendFileSync(path.join(UPLOAD_DIR, `${hash}.${ext}`), fse.readFileSync(path.join(tempDir, chunk)));
        });

    // 删除临时文件夹
    fse.removeSync(tempDir);
    fse.mkdir(tempDir);

    // 可能会返回文件下载地址
    ctx.body = "合并成功";
});

export default uploadRouter;
